{$CLEO .csi}

/*
    Implements GUI to call original GTA SA cheats    
    Controls (touch points are explained in CLEO Android readme):
      activation - via cleo script menu
      row up - touch point 4 
      row down - touch point 6      
      column left - touch point 2
      column right - touch point 8
      select cheat - touch point 5
      exit - menu button or any unused touch point
*/

thread 'CHEATS'

var 
    // this variables are 0 on the first start and on the others local variables are saved
    11@ : Integer // current row
    12@ : Integer // current column
end  

// check variables
if or
    11@ < 0
    11@ > 11
    12@ < 0
    12@ > 8
then
    11@ = 0
    12@ = 0
end    
    
// mutex var 0 is being used between CLEO scripts as GUI stuff ident,
// if it's 1 then some script GUI is shown by some CLEO script
0DDD: 0@ = get_mutex_var 0

// check all neded for activation conditions
// another cleo gui must not be open and player must be defined
0DDD: 0@ = get_mutex_var 0
if or
    0@ == 1  
    not Player.Defined($PLAYER_CHAR)
then
    jump @end_script
end
// player must be controllable, but with jetpack it's ok 
if
    not Player.Controllable($PLAYER_CHAR)
then
    if
        8A0C: not player $PLAYER_CHAR on_jetpack
    then
        jump @end_script
    end
end    

// set GUI mutex to 1, all other CLEO scripts will get this
0DDC: set_mutex_var 0 to 1  
 
// freez player
Player.CanMove($PLAYER_CHAR) = false
0575: set_actor $PLAYER_ACTOR pinned_position 1
Camera.Restore_WithJumpCut()
Camera.SetBehindPlayer()

// create cheat panel
08D4: 10@ = create_panel_with_title 'CHT' position 240.0 100.0 width 150.0 columns 1 interactive 1 background 1 alignment 0
gosub @update_column  
090E: set_panel 10@ active_row 11@

wait 500

while true
    wait 0
    
    // player checks
    if or
        0117: player $PLAYER_CHAR wasted
        0741: actor $PLAYER_ACTOR busted
    then
        break
    end
    
    // row switch
    0DE0: 0@ = get_touch_point_state 4 mintime 0
    0DE0: 1@ = get_touch_point_state 6 mintime 0        
    if and
        0@ == 1 // 4 is pressed
        1@ == 0 // 6 isn't
    then
        if 
            11@ > 0
        then
            11@ -= 1
        else
            11@ = 11
        end
        090E: set_panel 10@ active_row 11@
        wait 200
        continue
    end      
    if and
        0@ == 0 // 4 isn't pressed
        1@ == 1 // 6 is
    then
        if 
            11@ < 11
        then
            11@ += 1
        else
            11@ = 0
        end
        090E: set_panel 10@ active_row 11@
        wait 200
        continue
    end    
      
    // column switch
    0DE0: 0@ = get_touch_point_state 2 mintime 0
    if 
        0@ == 1 // if touch point 2 pressed 
    then // switch column left
        if 
            12@ > 0
        then
            12@ -= 1
        else
            12@ = 8
        end
        gosub @update_column
        090E: set_panel 10@ active_row 11@
        wait 250
        continue
    end
    0DE0: 0@ = get_touch_point_state 8 mintime 0
    if 
        0@ == 1 // if touch point 8 pressed 
    then // switch column right
        if 
            12@ < 8
        then
            12@ += 1
        else
            12@ = 0
        end
        gosub @update_column
        090E: set_panel 10@ active_row 11@
        wait 250
        continue
    end   
       
    // close
    0DE2: 0@ = get_menu_button_state
    if // menu button is pressed
        0@ == 1
    then
        break
    end 
    0DE0: 0@ = get_touch_point_state 1 mintime 500
    0DE0: 1@ = get_touch_point_state 3 mintime 500
    0DE0: 2@ = get_touch_point_state 7 mintime 500
    0DE0: 3@ = get_touch_point_state 9 mintime 500
    if or
        0@ == 1 // touch point 1 is pressed
        1@ == 1 // touch point 3 is pressed
        2@ == 1 // touch point 7 is pressed
        3@ == 1 // touch point 9 is pressed
    then
        break
    end  

    // use cheat
    0DE0: 0@ = get_touch_point_state 5 mintime 0
    0DE0: 1@ = get_touch_point_state 4 mintime 0
    0DE0: 2@ = get_touch_point_state 6 mintime 0        
    if and // center touch point 5 is pressed and 4 or 6 are not
        0@ == 1
        1@ == 0
        2@ == 0
    then
        03E6: remove_text_box
        var 
            0@ : Integer  
            1@ : Integer
            2@ : Integer
            3@ : Integer
        end                    
        0@ = 12@
        0@ *= 12
        0@ += 11@
        // 0@ stores cheat id
        if 
            0@ > 99
        then
            03E5: show_text_box 'CHTNO'
            break         
        end
        0DD0: 1@ = get_label_addr @earr_bool_cheats
        0DD1: 1@ = get_func_addr_by_cstr_name 1@
        1@ += 0@
        0DD8: 2@ = read_mem_addr 1@ size 1 fix_ib 0
        if 
            2@ == 0
        then
            2@ = 1
        else
            2@ = 0
        end
        // 1@ stores cheat bool state address
        // 2@ stores state to set for bool cheat
        0DD0: 3@ = get_label_addr @earr_cheat_funcs
        0DD1: 3@ = get_func_addr_by_cstr_name 3@        
        0@ *= 4
        3@ += 0@
        // 3@ stores cheat func ptr address        
        0DD8: 3@ = read_mem_addr 3@ size 4 fix_ib 0
        // 3@ stores cheat func ptr            
        if
            3@ > 0
        then
            // func cheat
            0DD2: context_call_func 3@
        else
            // bool cheat
            0DD9: write_mem_addr 1@ value 2@ size 1 add_ib 0 protect 0
        end
        // show text box with cheat state
        if 
            2@ == 1
        then
            03E5: show_text_box 'CHTACT'
        else
            03E5: show_text_box 'CHTDEA'
        end         
        break            
    end // use cheat
                   
end // button check loop

// remove panel
08DA: remove_panel 10@

// unfreez player
Player.CanMove($PLAYER_CHAR) = true
0575: set_actor $PLAYER_ACTOR pinned_position 0

// clear active GUI mutex    
0DDC: set_mutex_var 0 to 0

:end_script
end_thread

// updates panel column by column id
:update_column
if
    12@ == 0 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data 'CHT_0' 'CHT_1' 'CHT_2' 'CHT_3' 'CHT_4' 'CHT_5' 'CHT_6' 'CHT_7' 'CHT_8' 'CHT_9' 'CHT_10' 'CHT_11'
end
if
    12@ == 1 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data 'CHT_12' 'CHT_13' 'CHT_14' 'CHT_15' 'CHT_16' 'CHT_17' 'CHT_18' 'CHT_19' 'CHT_20' 'CHT_21' 'CHT_22' 'CHT_23'
end
if
    12@ == 2 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data 'CHT_24' 'CHT_25' 'CHT_26' 'CHT_27' 'CHT_28' 'CHT_29' 'CHT_30' 'CHT_31' 'CHT_32' 'CHT_33' 'CHT_34' 'CHT_35'
end
if
    12@ == 3 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data 'CHT_36' 'CHT_37' 'CHT_38' 'CHT_39' 'CHT_40' 'CHT_41' 'CHT_42' 'CHT_43' 'CHT_44' 'CHT_45' 'CHT_46' 'CHT_47' 
end
if
    12@ == 4 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data  'CHT_48' 'CHT_49' 'CHT_50' 'CHT_51' 'CHT_52' 'CHT_53' 'CHT_54' 'CHT_55' 'CHT_56' 'CHT_57' 'CHT_58' 'CHT_59' 
end
if
    12@ == 5 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data  'CHT_60' 'CHT_61' 'CHT_62' 'CHT_63' 'CHT_64' 'CHT_65' 'CHT_66' 'CHT_67' 'CHT_68' 'CHT_69' 'CHT_70' 'CHT_71' 
end
if
    12@ == 6 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data  'CHT_72' 'CHT_73' 'CHT_74' 'CHT_75' 'CHT_76' 'CHT_77' 'CHT_78' 'CHT_79' 'CHT_80' 'CHT_81' 'CHT_82' 'CHT_83' 
end
if
    12@ == 7 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data  'CHT_84' 'CHT_85' 'CHT_86' 'CHT_87' 'CHT_88' 'CHT_89' 'CHT_90' 'CHT_91' 'CHT_92' 'CHT_93' 'CHT_94' 'CHT_95' 
end
if
    12@ == 8 
then
    08DB: set_panel 10@ column 0 header 'DUMMY' data  'CHT_96' 'CHT_97' 'CHT_98' 'CHT_99' 'CHTDMY' 'CHTDMY' 'CHTDMY' 'CHTDMY' 'CHTDMY' 'CHTDMY' 'CHTDMY' 'CHTDMY'
end
return 

// mangled exported symbol name
:earr_cheat_funcs
hex
    "_ZN6CCheat17m_aCheatFunctionsE" 00
end     

:earr_bool_cheats
hex
    "_ZN6CCheat15m_aCheatsActiveE" 00
end    